package br.com.puertorico.model.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
import javax.persistence.Version;

/**
 * Cont&eacute;m os elementos fundamentais de todas as entidades do sistema.
 *
 * @author daniel.camargo
 * @version $Id$
 * @since 29/08/2009
 */
@MappedSuperclass
public abstract class BaseEntity implements Serializable {

	private static final long serialVersionUID = 7685980228797389535L;

	private static Long HASH_CODE_GENERATOR;

	@Transient
	private Long hashCode;

	@Version
	@Column(name = "versao")
	@Temporal(TemporalType.TIMESTAMP)
	private Date versao;

	public abstract Long getId();

	public abstract void setId(Long id);

	static {
		HASH_CODE_GENERATOR = 1L;
	}

	{
		hashCode = HASH_CODE_GENERATOR++;
	}

	public Date getVersao() {
		return versao;
	}

	public void setVersao(Date versao) {
		this.versao = versao;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean equals(Object entityCandidate) {
		if (entityCandidate == null) {
			return false;
		}
		if (entityCandidate instanceof BaseEntity) {
			BaseEntity canditado = (BaseEntity) entityCandidate;
			// testamos pelo id real
			if (getId() != null && canditado.getId() != null) {
				return getId().equals(canditado.getId());
				// testamos pelo id falso
			} else if (hashCode != null && canditado.hashCode != null) {
				return hashCode.equals(canditado.hashCode);
			}
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public int hashCode() {
		if (getId() != null) {
			return getId().hashCode();
		}
		return hashCode.hashCode();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String toString() {
		String idStr = (getId() == null) ? hashCode.toString() : getId()
				.toString();
		return new StringBuffer(idStr).append("@")
				.append(getClass().getSimpleName()).toString();
	}

}
